/// <reference path="../devextreme/ts/jquery.d.ts" />
/// <reference path="../devextreme/ts/dx.all.d.ts" />

($ => {
    class AdvancedSearch {
        constructor(options) {
            const defaultOptions = {
                visibleReset: true,
                visibleSearch: true,
            };

            this.options = { ...defaultOptions, ...options };

            this.ele = this.options.ele;
            this.view = this.options.view;
            this.data = this.options.data;
            this.onReset = this.options.onReset;
            this.onSearch = this.options.onSearch;

            this.init(this.ele, this.view, this.data);
        }

        init(ele, view, data) {
            const $ele = $(ele);
            const $amisContainer = $('<div style="--Form-item-gap: 5px;flex: 1; height:0;" />');

            $ele.css({ display: 'flex', flexDirection: 'column', flexWrap: 'nowrap' });

            $ele.append($amisContainer);
            $ele.append(this.createToolbar());

            if (view instanceof String) {
                view = JSON.parse(view);
            }

            this.amis = $amisContainer.amis({
                schema: view,
                data,
            });
        }

        createToolbar() {
            const { visibleReset, visibleSearch } = this.options;

            const items = [];

            if (visibleReset) {
                items.push({
                    widget: 'dxButton',
                    location: 'after',
                    options: {
                        text: '重置',
                        icon: 'revert',
                        focusStateEnabled: false,
                        onClick: this.reset.bind(this),
                    },
                });
            }

            if (visibleSearch) {
                items.push({
                    widget: 'dxButton',
                    location: 'after',
                    options: {
                        text: '搜索',
                        icon: 'search',
                        focusStateEnabled: false,
                        onClick: this.search.bind(this),
                    },
                });
            }

            const $toolbar = $('<div />').dxToolbar({ items });

            $toolbar.find('.dx-toolbar-items-container').css({
                height: '36px',
            });

            return $toolbar;
        }

        getAmisForm() {
            return this.amis.getComponentByName('form');
        }

        getAmisValues() {
            const values = this.getAmisForm()?.getValues() ?? {};
            return Object.keys(values).reduce((result, key) => {
                if (!key.startsWith('__')) {
                    result[key] = values[key];
                }
                return result;
            }, {});
        }

        updateView(view, formData) {
            this.view = view;
            this.formData = formData;

            if (view instanceof String || typeof view === 'string') {
                view = JSON.parse(view);
            }

            let data = formData;

            this.amis.updateSchema(view);
            this.amis.updateProps({ data });
        }

        updateData(data) {
            this.data = data;
            this.getAmisForm()?.setValues({ ...data });
        }

        reset() {
            this.getAmisForm()?.reset();

            if (this.formData) {
                this.updateData(this.formData);
            }

            if (this.onReset) {
                this.onReset();
            }
        }

        search() {
            if (this.onSearch) {
                const values = this.getAmisValues();
                this.onSearch(values);
            }
        }

        dispose() {
            this.amis.unmount();
        }
    }

    $.fn.advancedSearch = function (view, onSearch, options) {
        options ??= {};
        const advancedSearch = new AdvancedSearch({ ele: this[0], view, onSearch, ...options });
        return {
            updateView: advancedSearch.updateView.bind(advancedSearch),
            updateData: advancedSearch.updateData.bind(advancedSearch),
            reset: advancedSearch.reset.bind(advancedSearch),
            search: advancedSearch.search.bind(advancedSearch),
            dispose: advancedSearch.dispose.bind(advancedSearch),
        };
    };
})(jQuery);
